package foodmaterial.service.impl;

import foodmaterial.dao.CustomerDao;
import foodmaterial.dao.OtherDao;
import foodmaterial.dao.PermissionDao;
import foodmaterial.dto.CustomerInfoDto;
import foodmaterial.dto.MealsTypeDto;
import foodmaterial.entity.*;
import foodmaterial.service.CustomerService;
import foodmaterial.utils.Constants;
import foodmaterial.utils.PageUtil;
import foodmaterial.utils.PasswordUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class CustomerServiceImpl extends BaseService implements CustomerService {

    @Autowired
    private CustomerDao dao ;

    @Autowired
    private OtherDao otherDao ;

    @Autowired
    private PermissionDao permissionDao;

    private String checkRouterName(RouterInfo routerInfo) {
        RouterInfo ri = new RouterInfo() ;
        ri.setName(routerInfo.getName());
        List<RouterInfo> list = dao.selectRouterInfo(ri) ;
        return checkExist(list,routerInfo) ;
    }

    @Override
    @CacheEvict(cacheNames={ROUTER_INFO_CACHE},key = "#routerInfo.db")
    public String addRouterInfo(RouterInfo routerInfo) {
        String result = checkRouterName(routerInfo) ;
        if (result != null) return result ;
        routerInfo.setId(nextId());
        int row = dao.insertRouterInfo(routerInfo);
        if (row == 0) return "线路新增失败" ;
        return null ;
    }

    @Override
    @CacheEvict(cacheNames={ROUTER_INFO_CACHE},key = "#routerInfo.db")
    public String modifyRouterInfo(RouterInfo routerInfo) {
        String result = checkRouterName(routerInfo) ;
        if (result != null) return result ;
        int row = dao.updateRouterInfo(routerInfo);
        if (row == 0) return "线路修改失败" ;
        return null ;
    }

    @Override
    public List<RouterInfo> queryRouterInfo(RouterInfo routerInfo) {
        return dao.selectRouterInfo(routerInfo);
    }

    @Override
    @CacheEvict(cacheNames={ROUTER_INFO_CACHE},key = "#db")
    public List<RouterInfo> queryRouterInfo(String db) {
        RouterInfo routerInfo = new RouterInfo() ;
        return dao.selectRouterInfo(routerInfo);
    }

    private String checkSupplyTypeName(SupplyType supplyType) {
        SupplyType st = new SupplyType() ;
        st.setName(supplyType.getName());
        List<SupplyType> list = dao.selectSupplyType(st) ;
        return checkExist(list,supplyType) ;
    }

    @Override
    public String addSupplyType(SupplyType supplyType) {
        String result = checkSupplyTypeName(supplyType) ;
        if (result != null) return result ;
        supplyType.setId(nextId());
        int row = dao.insertSupplyType(supplyType);
        if (row <= 0) return "新增配送类型失败" ;
        return null ;
    }

    @Override
    public String modifySupplyType(SupplyType supplyType) {
        String result = checkSupplyTypeName(supplyType) ;
        if (result != null) return result ;
        int row = dao.updateSupplyType(supplyType);
        if (row <= 0) return "修改配送类型失败" ;
        return null ;
    }

    @Override
    public List<SupplyType> querySupplyType(SupplyType supplyType) {
        return dao.selectSupplyType(supplyType);
    }

    private String checkSupplyTeamName(SupplyTeam supplyTeam) {
        SupplyTeam st = new SupplyTeam() ;
        st.setName(supplyTeam.getName());
        List<SupplyTeam> list = dao.selectSupplyTeam(st) ;
        return checkExist(list,supplyTeam) ;
    }

    @Override
    public String addSupplyTeam(SupplyTeam supplyTeam) {
        String result = checkSupplyTeamName(supplyTeam);
        if (result != null) return result ;
        supplyTeam.setId(nextId());
        int row = dao.insertSupplyTeam(supplyTeam);
        if (row <= 0) return "新增配送小组失败" ;
        return null ;
    }

    @Override
    public String modifySupplyTeam(SupplyTeam supplyTeam) {
        String result = checkSupplyTeamName(supplyTeam);
        if (result != null) return result ;
        int row = dao.updateSupplyTeam(supplyTeam);
        if (row <= 0) return "修改配送小组失败" ;
        return null ;
    }

    @Override
    public List<SupplyTeam> querySupplyTeam(SupplyTeam supplyTeam) {
        return dao.selectSupplyTeam(supplyTeam);
    }

    private String checkSupplyAreaName(SupplyArea supplyArea) {
        SupplyArea sa = new SupplyArea() ;
        sa.setName(supplyArea.getName());
        List<SupplyArea> list = dao.selectSupplyArea(sa) ;
        return checkExist(list,supplyArea) ;
    }

    @Override
    public String addSupplyArea(SupplyArea supplyArea) {
        String result = checkSupplyAreaName(supplyArea);
        if (result != null) return result ;
        supplyArea.setId(nextId());
        int row = dao.insertSupplyArea(supplyArea);
        if (row <= 0) return "新增配送区域失败" ;
        return null ;
    }

    @Override
    public String modifySupplyArea(SupplyArea supplyArea) {
        String result = checkSupplyAreaName(supplyArea);
        if (result != null) return result ;
        int row = dao.updateSupplyArea(supplyArea);
        if (row <= 0) return "修改配送区域失败" ;
        return null ;
    }

    @Override
    public List<SupplyArea> querySupplyArea(SupplyArea supplyArea) {
        return dao.selectSupplyArea(supplyArea);
    }

    private static final String CUSTOMER_FLAG = "123456789abcdefghijklmnopqrstvuwxyz" ;

    public static String getCustomerSeq(CustomerSeq cs) {
        StringBuilder sb = new StringBuilder();
        sb.append(CUSTOMER_FLAG.charAt(cs.getCurrentFlag() - 1)) ;
        String i = Integer.toString(cs.getSeq()) ;
        for (int k = 0 ; k < 5 - i.length(); k++) sb.append('0');
        sb.append(i) ;
        if (cs.getSeq() >= 99999) {
            cs.setCurrentFlag(cs.getCurrentFlag() + 1);
            cs.setSeq(1);
        } else {
            cs.setSeq(cs.getSeq() + 1);
        }
        return sb.toString();
    }

    private String checkCustomerName(CustomerInfo customerInfo) {
        CustomerInfoDto dto = new CustomerInfoDto() ;
        dto.setName(customerInfo.getName());
        List<CustomerInfo> list = dao.selectCustomerInfo(dto) ;
        return checkExist(list,customerInfo) ;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String addCustomerInfo(CustomerInfo customerInfo) {
        String result = checkCustomerName(customerInfo) ;
        if (result != null) return result ;
        customerInfo.setId(nextId());
        customerInfo.setPassword(PasswordUtil.encodePassword(Constants.DEFAULT_PASSWORD));
        CustomerSeq cs = otherDao.selectCustomerSeq();
        customerInfo.setCode(getCustomerSeq(cs));
        otherDao.updateCustomerSeq(cs) ;
        int rows = dao.insertCustomerInfo(customerInfo);
        if (rows > 0) return null ;
        return "新增客户失败" ;
    }

    @Override
    public String modifyCustomerInfo(CustomerInfo customerInfo) {
        String result = checkCustomerName(customerInfo) ;
        if (result != null) return result ;
        int rows = dao.updateCustomerInfo(customerInfo);
        if (rows > 0) return null ;
        return "修改客户失败" ;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String modifyCustomerInfoOrder(List<CustomerInfo> customerInfos) {
        if (customerInfos == null || customerInfos.isEmpty()) return "至少选择2个客户再调整顺序号" ;
        int rows = dao.updateCustomerInfoOrder(customerInfos) ;
        if (rows <= 0) return "更新顺序号失败" ;
        return null;
    }

    @Override
    public int stopCustomer(CustomerInfo customerInfo) {
        return dao.stopCustomer(customerInfo);
    }

    @Override
    public String modifyPassword(CustomerInfoDto dto) {
        String result = PasswordService.checkPassword(dto.getPassword(),dto.getConfirmPassword());
        if (result != null) return result ;
        CustomerInfo u = dao.selectCustomerInfo(dto).get(0) ;
        if (PasswordUtil.matches(dto.getOldPassword(),u.getPassword()) == false) return "旧密码输入不对" ;
        dto.setPassword(PasswordUtil.encodePassword(dto.getPassword())) ;
        CustomerInfo ci = new CustomerInfo() ;
        ci.setId(dto.getId());
        ci.setPassword(dto.getPassword());
        dao.updateCustomerInfo(ci) ;
        return null;
    }

    @Override
    public String resetPassword(SysUser user) {
        String result = PasswordService.checkPassword(user.getPassword(),user.getConfirmPassword());
        if (result != null) return result ;
        CustomerInfo customerInfo = new CustomerInfo();
        customerInfo.setId(user.getId());
        customerInfo.setPassword(PasswordUtil.encodePassword(user.getPassword()));
        int row = dao.updateCustomerInfo(customerInfo);
        if (row == 0) return "密码重置不成功" ;
        return null ;
    }

    @Override
    public List<CustomerInfo> queryCustomerRoot() {
        return dao.selectCustomerRoot();
    }

    @Override
    public List<CustomerInfo> queryCustomerInfo(CustomerInfoDto dto) {
        return dao.selectCustomerInfo(dto);
    }

    @Override
    public List<CustomerInfo> queryCustomerInfoByType(List<String> params) {
        return dao.selectCustomerInfoByType(params);
    }

    @Override
    public List<String> queryDriver() {
        return dao.selectDriver();
    }

    @Override
    public List<MealsType> queryCustomerToTeam(Map<String,Object> params) {
        return dao.selectCustomerToTeam(params);
    }

    @Override
    public String addMealsType(MealsType mealsType) {
        MealsTypeDto dto = new MealsTypeDto() ;
        dto.setCustomerId(mealsType.getCustomerId());
        dto.setMealsTypeNameId(mealsType.getMealsTypeNameId());
        List<MealsType> list = dao.selectMealsType(dto);
        if (list.isEmpty() == false) {
            return "客户此餐别已经存在了" ;
        }
        mealsType.setId(nextId());
        int result = dao.insertMealsType(mealsType);
        if (result == 0) return "添加餐别失败" ;
        return null ;
    }

    @Override
    public String modifyMealsType(MealsType mealsType) {
        MealsTypeDto dto = new MealsTypeDto() ;
        dto.setCustomerId(mealsType.getCustomerId());
        dto.setMealsTypeNameId(mealsType.getMealsTypeNameId());
        List<MealsType> list = dao.selectMealsType(dto);
        if (list.isEmpty() == false && list.get(0).getId().longValue() != mealsType.getId().longValue()) {
            return "客户此餐别已经存在了" ;
        }
        int result = dao.updateMealsType(mealsType);
        if (result == 0) return "修改餐别失败" ;
        return null ;
    }

    @Override
    public int removeMealsType(MealsType mealsType) {
        return dao.deleteMealsType(mealsType);
    }

    @Override
    public List<MealsType> queryMealsType(MealsTypeDto dto) {
        List<MealsType> result = dto.getRecipe() == null ?
                dao.selectMealsType(dto) : dao.selectRecipeVipMealsType(dto);
        if (dto.getVip() != null && dto.getOriginalProcess() == null) {
            int index = 0 ;
            Set<Long> set = new HashSet<>(result.size() / 2 + 2) ;
            List<MealsType> temp = new ArrayList<>(result.size() / 2 + 2);
            for (MealsType mt : result) {
                if (set.contains(mt.getCustomerId())) {
                    MealsType mt1 = temp.get(index) ;
                    index++ ;
                    mt1.setTemplateName(mt1.getTemplateName() + "|" + mt.getTemplateName());
                } else {
                    temp.add(mt) ;
                    set.add(mt.getCustomerId()) ;
                }
            }
            result = temp ;
        }
        return result;
    }

    private String checkMealsTypeName(MealsTypeName mealsTypeName) {
        MealsTypeName mtn = new MealsTypeName() ;
        mtn.setName(mealsTypeName.getName());
        List<MealsTypeName> list = dao.selectMealsTypeName(mtn) ;
        return checkExist(list,mealsTypeName) ;
    }

    @Override
    @CacheEvict(cacheNames={MEALS_TYPE_NAME_CACHE},key = "#mealsTypeName.db")
    public String addMealsTypeName(MealsTypeName mealsTypeName) {
        String result = checkMealsTypeName(mealsTypeName) ;
        if (result != null) return result ;
        mealsTypeName.setId(nextId());
        int row = dao.insertMealsTypeName(mealsTypeName);
        if (row <= 0) return "新增餐别类别失败" ;
        return null ;
    }

    @Override
    @CacheEvict(cacheNames={MEALS_TYPE_NAME_CACHE},key = "#mealsTypeName.db")
    public String modifyMealsTypeName(MealsTypeName mealsTypeName) {
        String result = checkMealsTypeName(mealsTypeName) ;
        if (result != null) return result ;
        int row = dao.updateMealsTypeName(mealsTypeName);
        if (row <= 0) return "修改餐别类别失败" ;
        return null ;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames={MEALS_TYPE_NAME_CACHE},key = "#db")
    public String modifyMealsTypeNameOrderAndCalType(List<MealsTypeName> data,String db) {
        if (data == null || data.isEmpty()) return "至少有一条餐别明细" ;
        int rows = dao.updateMealsTypeNameOrderAndCalType(data);
        if (rows > 0) return null;
        return "调整显示顺序和统计类型失败";
    }

    @Override
    public int removeMealsTypeName(MealsTypeName mealsTypeName) {
        return dao.deleteMealsTypeName(mealsTypeName);
    }

    @Override
    public List<MealsTypeName> queryMealsTypeName(MealsTypeName mealsTypeName) {
        return dao.selectMealsTypeName(mealsTypeName);
    }

    @Override
    @Cacheable(cacheNames={MEALS_TYPE_NAME_CACHE},key="#db")
    public List<MealsTypeName> queryMealsTypeName(String db) {
        MealsTypeName mealsTypeName = new MealsTypeName();
        return dao.selectMealsTypeName(mealsTypeName);
    }

    @Override
    public List<String> queryMealsTypeCalName() {
        return dao.selectMealsTypeCalName();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String editCustomerFoodMaterialSupplier(Map<String,Object> data) {
        List<Long> customerIds = (List<Long>)data.get("customerId") ;
        if (customerIds == null || customerIds.isEmpty()) return "至少选择一个客户" ;
        Long supplierId = (Long)data.get("supplierId") ;
        if (supplierId == null) return "请选择一个供应商" ;
        Long foodMaterialId = (Long)data.get("foodMaterialId") ;
        if (foodMaterialId == null) return "请选择一条食材" ;
        List<CustomerFoodMaterialSupplier> list = new ArrayList<>() ;
        for (Long customerId :customerIds) {
            CustomerFoodMaterialSupplier cfms = new CustomerFoodMaterialSupplier() ;
            cfms.setId(nextId());
            cfms.setCustomerId(customerId);
            cfms.setFoodMaterialId(foodMaterialId);
            cfms.setSupplierId(supplierId);
            list.add(cfms) ;
        }
        dao.deleteCustomerFoodMaterialSupplier(customerIds,foodMaterialId);
        int rows = dao.insertCustomerFoodMaterialSupplier(list);
        if (rows > 0) return null ;
        return "设置客户食材供应商失败" ;
    }

    @Override
    public List<CustomerFoodMaterialSupplier> queryCustomerFoodMaterialSupplier(CustomerFoodMaterialSupplier customerFoodMaterialSupplier) {
        return dao.selectCustomerFoodMaterialSupplier(customerFoodMaterialSupplier);
    }

    @Override
    public String clearCustomer() {
        if (dao.checkCustomer() > 0) return "客户数据已经被使用了，不能进行清理工作" ;
        dao.truncateCustomer();
        dao.truncateRouter();
        dao.truncateSupplyArea();
        dao.truncateSupplyTeam();
        dao.truncateSupplyType();
        return null;
    }
}
